package lockDemo;

/**
 * volatile的作用是作为指令关键字，确保本条指令不会因编译器的优化而省略，且要求每次直接读值
 * 
 * 大家可能会误认为对变量i加上关键字volatile后，这段程序就是线程安全的。大家可以尝试运行上面的程序。
 * 下面是我本地运行的结果：992
 * 可能每个人运行的结果不相同。不过应该能看出，volatile是无法保证原子性的（否则结果应该是1000）。
 * 原因也很简单，i++其实是一个复合操作，包括三步骤：

　　（1）读取i的值。

　　（2）对i加1。

　　（3）将i的值写回内存。
volatile是无法保证这三个操作是具有原子性的，我们可以通过AtomicInteger或者Synchronized来保证+1操作的原子性。

注：上面几段代码中多处执行了Thread.sleep()方法，目的是为了增加并发问题的产生几率，无其他作用。
 * @author zybw-kf01
 *
 */
public class VolatileTest01 {
	volatile int i;

	//Synchronized
	public void addI() {
		i++;
		//下面2步骤 等于 i++;
//		int temp = i+1;
//		i = temp;

	}

	public static void main(String[] args) throws InterruptedException {
		final VolatileTest01 test01 = new VolatileTest01();
		for (int n = 0; n < 1000; n++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						Thread.sleep(10);

					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					test01.addI();
				}
			}).start();
		}

		Thread.sleep(8000);// 等待10秒，保证上面程序执行完成

		System.out.println(test01.i);
	}
}
